home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / text / misc / paginate.lha / Paginate / Paginate.c < prev    next >
C/C++ Source or Header  |  1993-04-27  |  9KB  |  362 lines

  1. /* Paginate.c Copyright © 1993 Fergus Duniho */
  2.  
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <time.h>
  7. #include "NumToStr.c"
  8.  
  9. size_t seglen(char *s);
  10. void overwrite (char *dest, char *str, size_t pos, size_t dlen, size_t slen);
  11. char *justify (char *str, size_t length);
  12. char *addstr (char *rstr, char *str);
  13. void print_usage ();
  14. void lineprint (char *line, int page, int lmar, int len);
  15. char *convert (char *str, int page, int len);
  16. char *timecnv (char *fmt, struct tm *tptr, size_t len);
  17. struct tm *get_time ();
  18.  
  19. main (int argc, char *argv[]) {
  20.     struct tm *t;  /* Time Pointer */
  21.     char c,
  22.     empty_str[] = "",
  23.     *header = empty_str,
  24.     *hd[3] = {empty_str, empty_str, empty_str},
  25.     *footer = "@C- #d -",
  26.     *ft[3] = {empty_str, empty_str, empty_str},
  27.     *lnfmt = empty_str; /* printf style format string for line numbering */
  28.     size_t i,          /* Loop Counter */
  29.     j,       /* General Purpose Variable */
  30.     top = 4,   /* These 4 values represent 1 inch margins for an */
  31.     bot = 57,  /* 8½ x 11 inch sheet of paper where each square */
  32.     lmar = 8,  /* inch is 6 lines by 10 characters, which will be */
  33.     rmar = 65, /* printed on a printer which puts a ½ inch margin */
  34.            /* at the top and a ¼ inch margin on the side. */
  35.     bottom,    /* Variable For Bottom Value Of Current Page */
  36.     page1 = 1, /* Page Number For First Page */
  37.     page,       /* Variable That Keeps Track Of Page Number */
  38.     linenum,   /* Line Number for Counting Lines on Page */
  39.     line = 1,  /* Line Number for Counting Lines in Document */
  40.     linelen,   /* Line Length For Headers & Footers */
  41.     tpage = 0, /* Flag that indicates whether there is a title page */
  42.     newline = 1, /* Flag which indicates start of a new line */
  43.     done = 0;  /* Flag which indicates when to leave a pair of loops */
  44.  
  45.     /* Parse Command Line For Argument Values */
  46.  
  47.     for (i = 1; i < argc; i++)
  48.     if (argv[i][0] == '-')
  49.         switch (argv[i][1]) {
  50.         case 'H':                        /* Default Header */
  51.             header = argv[++i];
  52.             break;
  53.         case 'h':
  54.             if (argv[i][2] == '0')       /* Even Header */
  55.             hd[0] = argv[++i];
  56.             else if (argv[i][2] == '1')  /* Odd Header */
  57.             hd[1] = argv[++i];
  58.             else if (argv[i][2] == 'f')  /* Header For 1st Page */
  59.             hd[2] = argv[++i];
  60.             break;
  61.         case 'F':                        /* Default Footer */
  62.             footer = argv[++i];
  63.             break;
  64.         case 'f':
  65.             if (argv[i][2] == '0')       /* Even Footer */
  66.             ft[0] = argv[++i];
  67.             else if (argv[i][2] == '1')  /* Odd Footer */
  68.             ft[1] = argv[++i];
  69.             else if (argv[i][2] == 'f')  /* Footer For 1st Page */
  70.             ft[2] = argv[++i];
  71.             break;
  72.         case 'N':
  73.             lnfmt = argv[++i];
  74.             break;
  75.         case 'r':                        /* Right Margin */
  76.             rmar = atoi(argv[++i]);
  77.             rmar = (rmar >= 1) ? rmar : 1;
  78.             break;
  79.         case 'l':                        /* Left Margin */
  80.             lmar = atoi(argv[++i]);
  81.             lmar = (lmar >= 1) ? lmar : 1;
  82.             break;
  83.         case 't':                        /* Top Line */
  84.             top = atoi(argv[++i]);
  85.             top = (top >= 1) ? top : 1;
  86.             break;
  87.         case 'b':                        /* Bottom Line */
  88.             bot = atoi(argv[++i]);
  89.             break;
  90.         case 'p': /* Page Number */
  91.             page1 = atoi(argv[++i]);
  92.             break;
  93.         case 'T':                        /* Title Page */
  94.             tpage = 1;
  95.             break;
  96.         default:
  97.             print_usage ();
  98.             break;
  99.         }
  100.         else
  101.         print_usage ();
  102.  
  103.     if (bot <= top) {
  104.     perror ("The bottom value should be greater than the top value.\n");
  105.     exit (0);
  106.     }
  107.  
  108.     /* Set Values for Footer and Header Strings */
  109.  
  110.     t = get_time();
  111.     footer = timecnv(footer, t, rmar);
  112.     header = timecnv(header, t, rmar);
  113.  
  114.     if (hd[0] == empty_str)
  115.     hd[0] = header;  /* Header For Even Pages */
  116.     else
  117.     hd[0] = timecnv(hd[0], t, rmar);
  118.  
  119.     if (hd[1] == empty_str)
  120.     hd[1] = header;  /* Header For Odd Pages */
  121.     else
  122.     hd[1] = timecnv(hd[1], t, rmar);
  123.  
  124.     if (hd[2] == empty_str)
  125.     hd[2] = header;  /* Header For The First Page */
  126.     else
  127.     hd[2] = timecnv(hd[2], t, rmar);
  128.  
  129.     if (ft[0] == empty_str)
  130.     ft[0] = footer;  /* Footer For Even Pages */
  131.     else
  132.     ft[0] = timecnv(ft[0], t, rmar);
  133.  
  134.     if (ft[1] == empty_str)
  135.     ft[1] = footer;  /* Footer For Odd Pages */
  136.     else
  137.     ft[1] = timecnv(ft[1], t, rmar);
  138.  
  139.     if (ft[2] == empty_str)
  140.     ft[2] = footer;  /* Footer For The First Page */
  141.     else
  142.     ft[2] = timecnv(ft[2], t, rmar);
  143.  
  144.  
  145.     page = page1;
  146.  
  147.     /* Paginate Standard Input Into Standard Output */
  148.  
  149.     while (!done) {
  150.     if (tpage) {
  151.         footer = header = empty_str; /* Turns header and footer off. */
  152.         tpage = 0; /* No more than one title page. */
  153.         page--; /* Assures that page will equal page1 next time round */
  154.     }
  155.     else {
  156.         j = (page == page1) ? 2 : (page & 1);
  157.         header = hd[j];
  158.         footer = ft[j];
  159.     }
  160.     bottom = (*footer == 0) ? bot : bot - 2;
  161.  
  162.     for (linenum = 1; linenum < top; linenum++)
  163.         putchar ('\n');
  164.  
  165.     if (*header != 0) {
  166.         lineprint (header, page, lmar, rmar);
  167.         putchar ('\n');
  168.         linenum += 2;
  169.     }
  170.  
  171.     while (linenum <= bottom && !done) {
  172.         if ((c = getc(stdin)) != EOF) {
  173.         if (newline) {
  174.             if (lnfmt != empty_str)
  175.             printf (lnfmt, line++);
  176.             newline = 0;
  177.         }
  178.         if (c == 12)
  179.             break;
  180.         putchar (c);
  181.         if (c == '\n') {
  182.             linenum++;
  183.             newline = 1;
  184.         }
  185.         }
  186.         else
  187.         done = 1;
  188.     }
  189.     if (*footer != 0) {
  190.         for (; linenum <= bottom; linenum++)
  191.         putchar ('\n');
  192.         putchar ('\n');
  193.         lineprint (footer, page, lmar, rmar);
  194.     }
  195.     putchar (12);
  196.     page++;
  197.     }
  198. }
  199.  
  200. void lineprint (char *line, size_t page, size_t lmar, size_t len) {
  201.     char *str1, *str2;
  202.     size_t i;
  203.  
  204.     str1 = convert(line, page, len);
  205.     str2 = justify(str1, len);
  206.     for (i = 1; i < lmar; i++)
  207.     putchar (' ');
  208.     puts (str2);
  209.     free (str1);
  210.     free (str2);
  211. }
  212.  
  213. void print_usage () {
  214.     fprintf (stderr,
  215.     "Paginate V1.00 Copyright © 1993 Fergus Duniho\n\n"
  216.     "Usage: Paginate <infile >outfile -F/K,-f0/K,-f1/K,-ff/K,-H/K,-h0/K\n"
  217.     "       -h1/K,-hf/K,-N/K,-t/K/N,-b/K/N,-l/K/N,-r/K/N,-p/K/N,-T/S\n"
  218.     " -H -h0 -h1 -hf Default, Even, Odd, and First Page Headers\n"
  219.     " -F -f0 -f1 -ff Default, Even, Odd, and First Page Footers\n"
  220.     " -N Line Number String -t Top Line -b Bottom Line -p First Page #\n"
  221.     " -l Left Margin -r Relative Right Margin -T Title page\n"
  222.     "\nDefault: Paginate -F \"@C- #d -\" -H \"\" -N \"\" -l 8 -r 65 -t 4 -b 57 -p 1\n");
  223.     exit (0);
  224. }
  225.  
  226. char *convert (char *str, size_t page, size_t len) {
  227.     char *rstr = (char *)malloc(len + 1);
  228.     char *r = rstr;
  229.     while (*str != 0) {
  230.     if (*str != '#')
  231.         *rstr++ = *str;
  232.     else
  233.         switch (*(++str)) {
  234.         case '#':
  235.             *rstr++ = '#';
  236.             break;
  237.         case 'r':
  238.             rstr = addstr(rstr, roman(page, 0));
  239.             break;
  240.         case 'R':
  241.             rstr = addstr(rstr, roman(page, 1));
  242.             break;
  243.         case 'd':
  244.             rstr = addstr(rstr, itoa(page, 10));
  245.             break;
  246.         case 'o':
  247.             rstr = addstr(rstr, itoa(page, 8));
  248.             break;
  249.         case 'b':
  250.             rstr = addstr(rstr, itoa(page, 2));
  251.             break;
  252.         case 'x':
  253.             rstr = addstr(rstr, itoa(page, 16));
  254.             break;
  255.         }
  256.     str++;
  257.     }
  258.     *rstr = 0;
  259.     return r;
  260. }
  261.  
  262.  
  263.  
  264. char *addstr (char *rstr, char *str) {
  265.     while ((*rstr++ = *str++) != 0);
  266.     return --rstr;
  267. }
  268.  
  269. char *justify (char *str, size_t length) {
  270.     size_t pos = 0, len;
  271.     char *line = (char *)malloc(length + 1);
  272.     char *ch = line;
  273.     size_t i;
  274.  
  275.     for (i = 0; i < length; i++)
  276.     *ch++ = ' ';
  277.     *ch = 0;
  278.  
  279.     while (*str != 0) {
  280.     if (*str == '@') {
  281.         if (*(++str) == 'R')
  282.         pos = length - seglen(++str);
  283.         else if (*str == 'C')
  284.         pos = (length - seglen(++str)) / 2;
  285.         else if (*str == '-') {
  286.         if (isxdigit(*(++str))) {
  287.             if (isdigit(*str))
  288.             pos -= (*str - '0');
  289.             else if (islower(*str))
  290.             pos -= ((*str - 'a') + 10);
  291.         }
  292.         str++;
  293.         }
  294.         else {
  295.         if (isxdigit(*str)) {
  296.             if (isdigit(*str))
  297.             pos += (*str - '0');
  298.             else if (islower(*str))
  299.             pos += ((*str - 'a') + 10);
  300.         }
  301.         else if (*str == 'L')
  302.             pos = 0;
  303.         str++;
  304.         }
  305.     }
  306.     else {
  307.         len = seglen(str);
  308.         overwrite(line, str, pos, length, len);
  309.         str += len;
  310.     }
  311.     }
  312.     return line;
  313. }
  314.  
  315. void overwrite (char *dest, char *str, size_t pos, size_t dlen, size_t slen) {
  316.     if (pos > dlen)
  317.     return;
  318.     dest += pos;
  319.     while (slen-- && *dest && *str)
  320.     *dest++ = *str++;
  321. }
  322.  
  323. size_t seglen(char *s) {
  324.     size_t len = 0;
  325.  
  326.     while (1) {
  327.     if (*s == '@')
  328.         if (*(++s) == '@')
  329.         len++;
  330.         else
  331.         return len;
  332.     else if (*s == 0)
  333.         return len;
  334.     else
  335.         len++;
  336.     s++;
  337.     }
  338. }
  339.  
  340. char *timecnv (char *fmt, struct tm *tptr, size_t len) {
  341.     char *s;
  342.  
  343.     if (*fmt == 0)
  344.     return fmt;
  345.     if ((s = (char *)malloc(len + 1)) == 0) {
  346.     perror ("Out of memory.");
  347.     exit (2);
  348.     }
  349.     if (strftime(s, len, fmt, tptr) == 0) {
  350.     fprintf (stderr, "The expansion of %s is too long.\n", fmt);
  351.     exit (2);
  352.     }
  353.     return s;
  354. }
  355.  
  356. struct tm *get_time () {
  357.     time_t *tod;
  358.  
  359.     time (tod);
  360.     return localtime(tod);
  361. }
  362.